#ifndef _USB_H
#define _USB_H 1

//define switcher 
#define DEBUG 1
#define TC       1

#define 	BIT0	0x01
#define 	BIT1	0x02
#define 	BIT2	0x04
#define 	BIT3	0x08
#define 	BIT4	0x10
#define 	BIT5	0x20
#define 	BIT6	0x40
#define 	BIT7	0x80
#define 	BIT8	0x100
#define 	BIT9	0x200
#define 	BIT10	0x400
#define 	BIT11	0x800
#define 	BIT12	0x1000
#define 	BIT13	0x2000
#define 	BIT14	0x4000
#define 	BIT15	0x8000
#define 	BIT16	0x10000
#define 	BIT17	0x20000
#define 	BIT18	0x40000
#define 	BIT19	0x80000
#define 	BIT20	0x100000
#define 	BIT21	0x200000
#define 	BIT22	0x400000
#define 	BIT23	0x800000
#define 	BIT24	0x1000000
#define 	BIT25	0x2000000
#define 	BIT26	0x4000000
#define 	BIT27	0x8000000
#define 	BIT28	0x10000000
#define 	BIT29	0x20000000
#define 	BIT30	0x40000000
#define 	BIT31	0x80000000

typedef unsigned char BYTE;
typedef unsigned int  WORD;
typedef unsigned long DWORD;
typedef unsigned char BOOL;

enum BOOLEAN {FALSE, TRUE};
typedef struct _LIST_ENTRY 
{
  struct _LIST_ENTRY  *ForwardLink;
  struct _LIST_ENTRY  *BackLink;
} LIST_ENTRY;

/******************************************************************************
    Function:
        InitializeList

    Description:
        Initialize the head of the list. The caller must allocate the memory
        for the list. This function must be called before the other linked list
        functions can be used.

    Entry:
        LIST_ENTRY* List

    Exit:
        None
******************************************************************************/
void InitializeList ( LIST_ENTRY       *List  );

/******************************************************************************
    Function:
        IsListEmpty

    Description:
        Return 'true' is the list contains zero nodes. Otherwise return 'false'
        The list must have been initialized with InitializeList () before using 
        this function.

    Entry:
        LIST_ENTRY* List. Points to the head of the list to test.

    Exit:
        'true' if the list contains zero nodes. Otherwise return 'false'
******************************************************************************/
BOOLEAN IsListEmpty (  LIST_ENTRY  *List  );

/******************************************************************************
    Function:
        InsertTailList

    Description:
        Insert a node at the end of a doubly linked list. The list must have 
        been initialized with InitializeList before using this function.

    Entry:
        LIST_ENTRY* ListHead.   Head of a a doubly linked list.
        LIST_ENTRY* Entry.      Element to insert at the beginning of list

    Exit:
        None
******************************************************************************/
void RemoveEntryList ( LIST_ENTRY  *Entry );

/******************************************************************************
    Function:
        InsertTailList

    Description:
        Insert a node at the end of a doubly linked list. The list must have 
        been initialized with InitializeList before using this function.

    Entry:
        LIST_ENTRY* ListHead.   Head of a a doubly linked list.
        LIST_ENTRY* Entry.      Element to insert at the beginning of list

    Exit:
        None
******************************************************************************/
void InsertTailList (  LIST_ENTRY  *ListHead,  LIST_ENTRY  *Entry  );



#define _CR(Record, TYPE, Field)  ((TYPE *) ((BYTE *) (Record) - (BYTE *) &(((TYPE *) 0)->Field)))

#define CONTROLLER_FROM_LIST_ENTRY(Node)   _CR (Node, HCStrucType, lControllerList)
#define DEVICE_FROM_LIST_ENTRY(Node) _CR (Node, DeviceInfoType, lDeviceList)

/////PID
#define    OUTPID    0xe1
#define    INPID       0x69
#define    SOFPID    0xa5
#define    SETUPPID 0x2d

#define    DATA0PID 0xc3
#define    DATA1PID 0x4b
#define    DATA2PID 0x87
#define    MDATAPID 0x0f

#define    ACKPID     0xd2
#define    NAKPID     0x5a
#define    STALLPID 0x1e
#define    NYETPID   0x96


#define    PREPID      0x3c
#define    ERRPID     0x3c
#define    SPLITPID  0x78
#define    PINGPID   0xb4
#define    RESERVEDPID   0xf0

//---------bRequest
#define   GET_STATUS     0
#define  CLEAR_FEATURE  1
#define  SET_FEATURE    3
#define  SET_ADDRESS  5
#define  GET_DESCRIPTOR 6
#define  SET_DESCRIPTOR  7
#define  GET_CONFIGURATION 8
#define  SET_CONFIGURATION  9
#define  GET_INTERFACE  10
#define   SET_INTERFACE 11
#define   SYNCH_FRAME   12


//--------Descriptor Types , wValue
#define  DEVICE  1
#define  CONFIGURATION 2
#define  STRING  3
#define  INTERFACE  4
#define  ENDPOINT  5
#define  DEVICE_QUALIFIER  6
#define  OTHER_SPEED_CONFIGURATION  7
#define  INTERFACE_POWER  8

//--------device class, subclass, protocol
#define  INTERFACECLASS  0
#define  AUDIOCLASS          1
#define  COMNC_CDCCLASS  2  
#define  HIDClass                 3
#define  PHYSICALDEVICECLASS 5
#define  STILLIMAGECLASS      6
#define  PRINTCLASS                7
#define  MassStorageClass      8
#define  HUBCLASS                  9
#define  CDCDATACLASS         10
#define  SMARTCARDCLASS    11
#define  SECURITYCONTENTCALASS 13
#define  VEDIOCLASS              14
#define  PERSONHEALTHCARECLASS 15
#define  WIRELESSCLASS          0xe0

//--------
#define Stalled 0x01
#define TimeOut 0x02
#define OtherError 0x04


#define   UHCITYPE    1
#define   OHCITYPE    2
#define   EHCITYPE    4

#define	Low_Speed_Device   1
#define	Full_Speed_Device   2
#define	High_Speed_Device  4

typedef   
struct  deviceDescriptor
{

         BYTE     bLength;
	  BYTE     bDescriptorType;
	  WORD  wbcdUSB;
	  BYTE    bDeviceClass;
	  BYTE    bDeviceSubClass;
	  BYTE    bDeviceProtocol;
	  BYTE    bMaxPacketSize;
	  WORD    widVendor;
	  WORD    widProduct;
	  WORD    wbcdDevice;
	  BYTE      biManufacture;
	  BYTE      biProduct;
	  BYTE      biSerialNumber;
	  BYTE      bNumConfigurations;
}deviceDescriptorType;


typedef    
struct  configurationDescriptor
{

         BYTE     bLength;
	  BYTE     bDescriptorType;
	  WORD  wTotalLength;
	  BYTE    bNumInterfaces;
	  BYTE    bConfigurationValue;
	  BYTE    iConfiguration;
	  BYTE    bmAttributes;
	  BYTE    bMaxPower;
}configurationDescriptorType;

typedef    
struct  interfaceDescriptor
{

          BYTE     bLength;
	  BYTE     bDescriptorType;
	  BYTE     bInterfaceNumber;
	  BYTE     bAlternateSetting;
	  BYTE     bNumEndpoints;
	  BYTE     bInterfaceClass;
	  BYTE     bInterfaceSubClass;
	  BYTE     bInterfaceProtocol;
	  BYTE     iInterface;
}interfaceDescriptorType;


typedef  
struct  endpointDescriptor
{

          BYTE     bLength;
	  BYTE     bDescriptorType;
	  BYTE     bEndpointAddress;
	  BYTE     bmAttributes;
	  WORD     wMaxPacketSize;
	  BYTE     bInterval;	 
}endpointDescriptorType;

typedef   
struct RequstFormat
{
        BYTE      bmRequestType;
	BYTE      bRequest;
	WORD   wValue;
	WORD   wIndex;
	WORD   wLength;
}RequstFormatType;



typedef 
struct EHCIDescriptor
{
}EHCIDescriptorType;



typedef
struct DevDriverMethod
{
	void		(* DevInit)(void * ptr);

}DevDriverMethodType;

typedef struct DeviceInfo DeviceInfoType;
typedef struct DeviceInfo  * DeviceInfoPtr;
struct DeviceInfo{ 
		       LIST_ENTRY 	  	lDeviceList;
			LIST_ENTRY		lDeviceUnderControllerList;	   	
			struct HCStruc *   pHCStrucPtr;    			
			BYTE 			bDeviceType;     
			BYTE                     bSubClassCode;
			BYTE                     bProtocolCode;
			WORD 			wVendorId;        
			WORD 			wDeviceId;         
			BYTE                     sManufacture[32];
			BYTE                     sProduct[32];
			BYTE                     sSerialNumber[32];

			BYTE 			bHubPortNumber; //port index base 1
			BYTE 			bDeviceAddress;  
			BYTE 			bEndpointNum;   
			BYTE 			bEndpointSpeed; 
			WORD 			wEndp0MaxPacket	; //    endpoint zero (only 8, 16, 32, or 64 are valid)

			BYTE			bBulkInEndpoint;
			WORD			wBulkInMaxPkt;
			BYTE                     bBulkInToggle;
		        BYTE			bBulkOutEndpoint;
			WORD			wBulkOutMaxPkt;
			BYTE                     bBulkOutToggle;
			BYTE			bIntEndpoint;
			BYTE			bInterval;
			BYTE 			bIntEndPointToggle;
			WORD		 	wIntMaxPkt; 
			BYTE		       bDataSync;

			BYTE 			bNumConfigs;
			BYTE 			bConfigNum;
			BYTE 			bInterfaceNum;
			BYTE 			bAltSettingNum;

			void * 			ptrPollTD;
			void * 			ptrPollED;
			BYTE 			bHubNumPorts;
		       BYTE 			bHubPowerOnDelay;
			WORD			wIncompatFlags;
	         	BYTE 			bHubDeviceNumber;

			DevDriverMethodType * 	pDevDriver; //device method
			void	*	pDevData;// device class specific data			
};

typedef 
struct ControllerAccessMethod
{
	   void  (*controllerInitial)(void * pHC);
          BYTE (*ControlTransfer)(DeviceInfoPtr ptr,  RequstFormatType * RFPtr);
	   BYTE (*bulkTransfer)(DeviceInfoPtr DIPtr, BYTE direction, BYTE * bufferPtr,WORD length,WORD * TransLength);	  
	   BYTE (*interruptTransfer)(DeviceInfoPtr DIPtr, BYTE direction, BYTE * bufferPtr,WORD length,WORD * TransLength);
	   BYTE *(* pointToDevBuffer)(DeviceInfoPtr ptr);
	   void (* DevPortInit)(DeviceInfoPtr ptr,BYTE portIndex);	   
	   
}ControllerAccessMethodType;




typedef 
struct HCStruc	{	
		       LIST_ENTRY  lControllerList;	//
		       LIST_ENTRY  lDeviceList; // device list under this controller
		       WORD    wPortBitMap; //how many ports under this controller
		       WORD    wPortDeviceBitMap;//which port plugged device.
			BYTE 	bHCType;     //
			DWORD 	dHcdDataArea;// memory address.
			DWORD 	dBaseAddress;   //
			BYTE 	bNumPorts;       //can canceled.
			BYTE	        bHCFlag;
	 		WORD 	wBusDevFuncNum;   //PCI address
			WORD	pIRQInfoPtr;
			void *	pDescriptorPtr; //pointer to descriptor 
			ControllerAccessMethodType *	pHCDPointer;
			WORD	       wAsyncListSize; //EHCI USE
			BYTE	        bOpRegOffset; //EHCI use
			BYTE	        indexPME; //EHCI USE
			BYTE              bMaxAddress;//max usb address on the USB.
}HCStrucType;

/////function declaration
  extern "C"    BYTE Read_PCI_Byte (BYTE bus,BYTE dev,BYTE func,BYTE reg);
  extern "C"   WORD Read_PCI_Word( BYTE bus,BYTE dev,BYTE func,BYTE reg);
  extern "C"   DWORD Read_PCI_DWord (BYTE bus,BYTE dev,BYTE func,BYTE reg);
  extern "C"   void Write_PCI_Byte(BYTE bus,BYTE dev,BYTE func,BYTE reg,BYTE value);
  extern "C"    BYTE readPortBYTE (WORD portIndex);
  extern "C"	WORD readPortWORD (WORD portIndex);
  extern "C"    DWORD readPortDWORD (WORD portIndex);
  extern "C"    void writePortBYTE (WORD portIndex, BYTE value);
  extern "C"    void writePortWORD (WORD portIndex, WORD value);
  extern "C"	void writePortDWORD (WORD portIndex, DWORD value);
  extern "C"   void  writeMemDWORD(DWORD memAddress, DWORD value);
  extern "C"   DWORD  getMemDWORD(DWORD memAddress);
  extern "C"   DWORD getMMIODWORD(DWORD memAddress);
  extern "C" 	void setMemDWORD(DWORD memAddress,DWORD AndValue,DWORD OrValue);
  extern "C"    void coreSetLimits(WORD arg1,WORD arg2);



void initUSB();

/******************************************************************************
    Function:
        initController

    Description:
	allocate memory for a controller as  HCStrucType type.
	insert this controller into USBControllerList.
	init lDeviceList in HCStrucType type.

    Entry:
	None

    Exit:
        HCStrucType pointer.
******************************************************************************/
void initController(BYTE bus,BYTE dev,BYTE func);


/******************************************************************************
    Function:
      getUSBDeviceList

    Description:
  	get USBDeviceList.

    Entry:
	none

    Exit:
	return USBDeviceList
******************************************************************************/
LIST_ENTRY *getUSBDeviceList();

/******************************************************************************
    Function:
        getUHCIMethod

    Description:
	return UHCI interface.

    Entry:
	none

    Exit:
        return UHCI method interface 
******************************************************************************/
ControllerAccessMethodType * getUHCIMethod();

/******************************************************************************
    Function:
      devInitialize

    Description:
  	init  device on specified port , and save information in device description.

    Entry:
	pHC  -- host controller description
	portIndex  -- port index under host controller	

    Exit:
	none
******************************************************************************/
void devInitialize(HCStrucType * pHC,BYTE portIndex);

void  storeStringDescriptor(BYTE * SourceStr, BYTE * DestStr);
void  parseConfigurationString(BYTE * stringPtr,  DeviceInfoPtr devicePtr);

#ifdef DEBUG  
void testStorage();
void testHID();
void showDeviceInfo(DeviceInfoPtr devicePtr);
void showAllDevice();
void showController(HCStrucType * HCPtr);
void showAllController();
void getHIDdevice();
#endif


#endif
